/*Z initrd线性地址空间（由低至高），线程可直接访问：
    部分                大小
-------------------------------
    initrd ELF          编译确定(尾页对齐)      ui_v_reg.end
    IPC buffer          4K
    bootinfo            4K
    (额外的bootinfo)    页对齐                  it_v_reg.end


initrd的rootserver内核对象，位于物理内存最高部分（由低至高），线程不可直接访问（除上面已映射部分）：
    CNode               32*8K
    (额外的bootinfo)    2^n*4K
    VSpace(一级)        4K
    ASID(PCID) pool     4K
    IPC buffer          4K
    bootinfo            4K
    initrd线性空间页表(除一级)
    TCB                 2K
    (最小的调度上下文)  256
    (老旧DMA根表        4K
          上下文表      256×4K
          顶级页表      设备数×4K
          其它页表      若干×4K)


*/

/*
 * Copyright 2014, General Dynamics C4 Systems
 *
 * SPDX-License-Identifier: GPL-2.0-only
 */

#include <config.h>
#include <kernel/boot.h>
#include <machine/io.h>
#include <model/statedata.h>
#include <object/interrupt.h>
#include <arch/object/interrupt.h>
#include <arch/machine.h>
#include <arch/kernel/apic.h>
#include <arch/kernel/boot.h>
#include <arch/kernel/boot_sys.h>
#include <arch/kernel/vspace.h>
#include <machine/fpu.h>
#include <arch/machine/timer.h>
#include <arch/object/ioport.h>
#include <linker.h>
#include <util.h>

#include <plat/machine/intel-vtd.h>

#define MAX_RESERVED 1                              /*Z 用途是处理引导时命令行参数传递的加载模块 */
BOOT_DATA static region_t reserved[MAX_RESERVED];   /*Z 要保留的initrd线性地址区域。相当于一个本地临时变量 */

/* functions exactly corresponding to abstract specification */
/*Z 初始化所有硬件中断的基本属性和状态全局变量(还需进一步设置)，赋予中断控制器访问能力 */
BOOT_CODE static void init_irqs(cap_t root_cnode_cap)
{
    irq_t i;
    /*Z 设置所有硬件中断的基本属性和状态全局变量 */
    for (i = 0; i <= maxIRQ; i++) {
        if (i == irq_timer) {
            setIRQState(IRQTimer, i);
#ifdef ENABLE_SMP_SUPPORT
        } else if (i == irq_remote_call_ipi || i == irq_reschedule_ipi) {
            setIRQState(IRQIPI, i);
#endif /* ENABLE_SMP_SUPPORT */
#ifdef CONFIG_IOMMU
        } else if (i == irq_iommu) {
            setIRQState(IRQReserved, i);
#endif
        } else if (i == 2 && config_set(CONFIG_IRQ_PIC)) {
            /* cascaded legacy PIC */
            setIRQState(IRQReserved, i);
        } else if (i >= irq_isa_min && i <= irq_isa_max) {
            if (config_set(CONFIG_IRQ_PIC)) {
                setIRQState(IRQInactive, i);
            } else {/*Z PIC的0-15中断怎么在I/O APIC下使用????? */
                setIRQState(IRQReserved, i);
            }
        } else if (i >= irq_user_min && i <= irq_user_max) {
            if (config_set(CONFIG_IRQ_IOAPIC)) {
                setIRQState(IRQInactive, i);
            } else {
                setIRQState(IRQReserved, i);
            }
        } else {
            setIRQState(IRQReserved, i);
        }
    }
    Arch_irqStateInit();/*Z 初始化所有硬件中断状态全局变量，除定时器和IOMMU置保留，其它均置空闲 */
    /* provide the IRQ control cap *//*Z 赋予中断控制器能力 */
    write_slot(SLOT_PTR(pptr_of_cap(root_cnode_cap), seL4_CapIRQControl), cap_irq_control_cap_new());
}
/*Z 设备RAM、ROM，空闲内存和内核启动内存，作为untyped，记录在ndks_boot中，并在根CNode中创建相应的能力 */
BOOT_CODE static bool_t create_untypeds(
    cap_t root_cnode_cap,
    region_t boot_mem_reuse_reg)
{
    seL4_SlotPos     slot_pos_before;
    seL4_SlotPos     slot_pos_after;
    /*Z 设备RAM、ROM，及空闲区和内核启动代码区，作为untyped，记录在bootinfo列表中，并在根CNode中创建相应的能力 */
    slot_pos_before = ndks_boot.slot_pos_cur;
    create_device_untypeds(root_cnode_cap, slot_pos_before);/*Z 将正常RAM以外的所有地址区域认定为untyped设备内存(RAM或ROM，含1M以下正常RAM) */
    create_kernel_untypeds(root_cnode_cap, boot_mem_reuse_reg, slot_pos_before);
    /*Z 在ndks_boot中记录相应的能力索引范围 */
    slot_pos_after = ndks_boot.slot_pos_cur;
    ndks_boot.bi_frame->untyped = (seL4_SlotRegion) {
        slot_pos_before, slot_pos_after
    };
    return true;
}
/*Z 将initrd最终加载区域加入ndks_boot保留区，系统可用内存(除initrd及以下的，包括内核本身)加入ndks_boot保留区和空闲区；
在物理内存顶部为initrd线程分配rootserver数据结构内存。*/
BOOT_CODE static void arch_init_freemem(p_region_t ui_p_reg, v_region_t v_reg,
                                        mem_p_regs_t *mem_p_regs, word_t extra_bi_size_bits)
{
    ui_p_reg.start = 0;/*Z 注意：这里赋值0！！！从物理地址0～内核～initrd都保留起来 */
    reserved[0] = paddr_to_pptr_reg(ui_p_reg);/*Z 暂存initrd线性地址区域 */
    init_freemem(mem_p_regs->count, mem_p_regs->list, MAX_RESERVED, reserved, v_reg, extra_bi_size_bits);
}

/* This function initialises a node's kernel state. It does NOT initialise the CPU. */
/*Z 创建initrd线程，包括地址空间、IPC buffer、bootinfo、TCB、CNode、页表、有关能力等；
创建idle线程；初始化中断、IOMMU、系统运行状态，记录空闲内存等 */
BOOT_CODE bool_t init_sys_state(
    cpu_id_t      cpu_id,
    mem_p_regs_t  *mem_p_regs,          /*Z 1M以上可用物理内存区域图 */
    ui_info_t     ui_info,              /*Z 第1个加载模块(initrd)的最终加载信息 */
    p_region_t    boot_mem_reuse_p_reg, /*Z 引导代码占用的可再利用地址区域 */
    /* parameters below not modeled in abstract specification */
    uint32_t      num_drhu,             /*Z ACPI提供的IOMMU数量 */
    paddr_t      *drhu_list,            /*Z ACPI提供的IOMMU寄存器组起始物理地址列表 */
    acpi_rmrr_list_t *rmrr_list,        /*Z ACPI提供的IOMMU管理下的用于老旧设备的DMA保留内存区列表，每设备一项 */
    acpi_rsdp_t      *acpi_rsdp,        /*Z BIOS的ACPI-RSDP表 */
    seL4_X86_BootInfo_VBE *vbe,         /*Z Multiboot1提供的图形显示信息。不好 */
    seL4_X86_BootInfo_mmap_t *mb_mmap,  /*Z Multiboot提供的内存区域信息 */
    seL4_X86_BootInfo_fb_t *fb_info     /*Z Multiboot2提供的frame buffer */
)
{   /*Z cap_t在x86_64上是struct{u64[2]} */
    cap_t         root_cnode_cap;       /*Z 根CNode能力 */
    vptr_t        extra_bi_frame_vptr;  /*Z initrd地址空间额外的bootinfo地址 */
    vptr_t        bi_frame_vptr;        /*Z initrd地址空间bootinfo地址 */
    vptr_t        ipcbuf_vptr;          /*Z initrd地址空间IPC buffer地址 */
    cap_t         it_vspace_cap;        /*Z 根VSpace能力 */
    cap_t         it_ap_cap;
    cap_t         ipcbuf_cap;
    word_t        extra_bi_size = sizeof(seL4_BootInfoHeader);/*Z 额外的bootinfo大小。多一个头是为padding准备的 */
    pptr_t        extra_bi_offset = 0;
    uint32_t      tsc_freq;
    create_frames_of_region_ret_t create_frames_ret;
    create_frames_of_region_ret_t extra_bi_ret;
    /*Z 将物理地址区域映射为内核虚拟地址区域 */
    /* convert from physical addresses to kernel pptrs */
    region_t ui_reg             = paddr_to_pptr_reg(ui_info.p_reg);/*Z initrd物理区域在内核空间中的映射 */
    region_t boot_mem_reuse_reg = paddr_to_pptr_reg(boot_mem_reuse_p_reg);/*Z 引导代码物理区域在内核空间中的映射 */
    /*Z 将initrd物理区域映射为它自己的用户空间虚拟区域 */
    /* convert from physical addresses to userland vptrs */
    v_region_t ui_v_reg;/*Z initrd在自身虚拟地址空间的区域 */
    v_region_t it_v_reg;/*Z initrd线程(initrd+IPCbuffer_bootinfo)在自身虚拟地址空间的区域 */
    ui_v_reg.start = ui_info.p_reg.start - ui_info.pv_offset;
    ui_v_reg.end   = ui_info.p_reg.end   - ui_info.pv_offset;
    /*Z 在initrd后追加IPC buffer和bootinfo页 */
    ipcbuf_vptr = ui_v_reg.end;
    bi_frame_vptr = ipcbuf_vptr + BIT(PAGE_BITS);
    extra_bi_frame_vptr = bi_frame_vptr + BIT(PAGE_BITS);
    /*Z 将VESA图形信息作为一条额外的bootinfo */
    if (vbe->vbeMode != -1) {
        extra_bi_size += sizeof(seL4_X86_BootInfo_VBE);
    }
    if (acpi_rsdp) {/*Z 将ACPI-RSDP表作为一条额外的bootinfo */
        extra_bi_size += sizeof(seL4_BootInfoHeader) + sizeof(*acpi_rsdp);
    }
    if (fb_info && fb_info->addr) {/*Z 将framebuffer作为一条额外的bootinfo */
        extra_bi_size += sizeof(seL4_BootInfoHeader) + sizeof(*fb_info);
    }
    /*Z 将来自Multiboot的RAM区域图作为一条额外的bootinfo */
    word_t mb_mmap_size = sizeof(seL4_X86_BootInfo_mmap_t);
    extra_bi_size += mb_mmap_size;
    /*Z 将4字节的TSC频率作为一条额外的bootinfo */
    // room for tsc frequency
    extra_bi_size += sizeof(seL4_BootInfoHeader) + 4;
    word_t extra_bi_size_bits = calculate_extra_bi_size_bits(extra_bi_size);/*Z 额外的bootinfo大小（向上取2的幂，至少1页）*/
    /*Z 设定initrd线程的区域 */
    /* The region of the initial thread is the user image + ipcbuf and boot info */
    it_v_reg.start = ui_v_reg.start;
    it_v_reg.end = ROUND_UP(extra_bi_frame_vptr + BIT(extra_bi_size_bits), PAGE_BITS);
#ifdef CONFIG_IOMMU
    /* calculate the number of io pts before initialising memory */
    if (!vtd_init_num_iopts(num_drhu)) {/*Z 获取所有IOMMU共同支持的最少域数量和页表级数 */
        return false;
    }
#endif /* CONFIG_IOMMU */
    /*Z 将initrd最终加载区域加入ndks_boot保留区，系统可用内存(除initrd占用的)加入ndks_boot保留区和空闲区；
在物理内存顶部为initrd线程分配rootserver数据结构内存。*/
    arch_init_freemem(ui_info.p_reg, it_v_reg, mem_p_regs, extra_bi_size_bits);
    /*Z 初始化rootserver的CNode，创建一个指向自身且能操作本身的能力CSlot */
    /* create the root cnode */
    root_cnode_cap = create_root_cnode();
    /*Z 为rootserver创建全局I/O端口控制能力。未实现 */
    /* create the IO port cap */
    write_slot(
        SLOT_PTR(pptr_of_cap(root_cnode_cap), seL4_CapIOPortControl),
        cap_io_port_control_cap_new()
    );
    /*Z 为rootserver创建调度域控制能力。未实现 */
    /* create the cap for managing thread domains */
    create_domain_cap(root_cnode_cap);
    /*Z 初始化所有硬件中断的基本属性和状态全局变量(还需进一步设置)，赋予中断控制器访问能力 */
    /* initialise the IRQ states and provide the IRQ control cap */
    init_irqs(root_cnode_cap);
    /*Z 获取TSC的计数频率：MHZ */
    tsc_freq = tsc_init();
    /*Z 赋值initrd(rootserver)的部分bootinfo */
    /* populate the bootinfo frame */
    populate_bi_frame(0, ksNumCPUs, ipcbuf_vptr, extra_bi_size);
    region_t extra_bi_region = {    /*Z 额外bootinfo线性区域 */
        .start = rootserver.extra_bi,
        .end = rootserver.extra_bi + BIT(extra_bi_size_bits)
    };
    /*Z 赋值额外的bootinfo：来自Multiboot的VBE信息 */
    /* populate vbe info block */
    if (vbe->vbeMode != -1) {
        vbe->header.id = SEL4_BOOTINFO_HEADER_X86_VBE;
        vbe->header.len = sizeof(seL4_X86_BootInfo_VBE);
        memcpy((void *)(rootserver.extra_bi + extra_bi_offset), vbe, sizeof(seL4_X86_BootInfo_VBE));
        extra_bi_offset += sizeof(seL4_X86_BootInfo_VBE);
    }
    /*Z 赋值额外的bootinfo：来自ACPI的RSDP表 */
    /* populate acpi rsdp block */
    if (acpi_rsdp) {
        seL4_BootInfoHeader header;
        header.id = SEL4_BOOTINFO_HEADER_X86_ACPI_RSDP;
        header.len = sizeof(header) + sizeof(*acpi_rsdp);
        *(seL4_BootInfoHeader *)(rootserver.extra_bi + extra_bi_offset) = header;
        extra_bi_offset += sizeof(header);
        memcpy((void *)(rootserver.extra_bi + extra_bi_offset), acpi_rsdp, sizeof(*acpi_rsdp));
        extra_bi_offset += sizeof(*acpi_rsdp);
    }
    /*Z 赋值额外的bootinfo：来自Multiboot的framebuffer信息 */
    /* populate framebuffer information block */
    if (fb_info && fb_info->addr) {
        seL4_BootInfoHeader header;
        header.id = SEL4_BOOTINFO_HEADER_X86_FRAMEBUFFER;
        header.len = sizeof(header) + sizeof(*fb_info);
        *(seL4_BootInfoHeader *)(rootserver.extra_bi + extra_bi_offset) = header;
        extra_bi_offset += sizeof(header);
        memcpy((void *)(rootserver.extra_bi + extra_bi_offset), fb_info, sizeof(*fb_info));
        extra_bi_offset += sizeof(*fb_info);
    }
    /*Z 赋值额外的bootinfo：来自Multiboot的RAM区域图 */
    /* populate multiboot mmap block */
    mb_mmap->header.id = SEL4_BOOTINFO_HEADER_X86_MBMMAP;
    mb_mmap->header.len = mb_mmap_size;
    memcpy((void *)(rootserver.extra_bi + extra_bi_offset), mb_mmap, mb_mmap_size);
    extra_bi_offset += mb_mmap_size;
    /*Z 赋值额外的bootinfo：自行计算的TSC计数频率：MHZ。暂存在临时变量中 */
    /* populate tsc frequency block */
    {
        seL4_BootInfoHeader header;
        header.id = SEL4_BOOTINFO_HEADER_X86_TSC_FREQ;
        header.len = sizeof(header) + 4;
        *(seL4_BootInfoHeader *)(extra_bi_region.start + extra_bi_offset) = header;
        extra_bi_offset += sizeof(header);
        *(uint32_t *)(extra_bi_region.start + extra_bi_offset) = tsc_freq;
        extra_bi_offset += 4;
    }
    /*Z 赋值额外的bootinfo：剩余空间均视作padding。暂存在临时变量中 */
    /* provde a chunk for any leftover padding in the extended boot info */
    seL4_BootInfoHeader padding_header;
    padding_header.id = SEL4_BOOTINFO_HEADER_PADDING;
    padding_header.len = (extra_bi_region.end - extra_bi_region.start) - extra_bi_offset;
    *(seL4_BootInfoHeader *)(extra_bi_region.start + extra_bi_offset) = padding_header;

#ifdef CONFIG_KERNEL_MCS
    /* set up sched control for each core *//*Z 赋予rootserver对每个cpu的SchedControl能力 */
    init_sched_control(root_cnode_cap, CONFIG_MAX_NUM_NODES);
#endif
    /*Z 创建完整的页表及其访问能力 */
    /* Construct an initial address space with enough virtual addresses
     * to cover the user image + ipc buffer and bootinfo frames */
    it_vspace_cap = create_it_address_space(root_cnode_cap, it_v_reg);
    if (cap_get_capType(it_vspace_cap) == cap_null_cap) {
        return false;
    }
    /*Z 为bootinfo创建页表项和访问能力 */
    /* Create and map bootinfo frame cap */
    create_bi_frame_cap(
        root_cnode_cap,
        it_vspace_cap,
        bi_frame_vptr
    );
    /*Z 为额外bootinfo创建页表项和访问能力 */
    /* create and map extra bootinfo region */
    extra_bi_ret =
        create_frames_of_region(
            root_cnode_cap,     /*Z CNode */
            it_vspace_cap,      /*Z VSpace */
            extra_bi_region,    /*Z 额外bootinfo线性区域 */
            true,               /*Z 不好：pptr_to_paddr应该只括第1个值 */
            pptr_to_paddr((void *)(extra_bi_region.start - extra_bi_frame_vptr))
        );
    if (!extra_bi_ret.success) {
        return false;
    }
    ndks_boot.bi_frame->extraBIPages = extra_bi_ret.region;
    /*Z 为IPC buffer创建页表项和访问能力 */
    /* create the initial thread's IPC buffer */
    ipcbuf_cap = create_ipcbuf_frame_cap(root_cnode_cap, it_vspace_cap, ipcbuf_vptr);
    if (cap_get_capType(ipcbuf_cap) == cap_null_cap) {
        return false;
    }
    /*Z 为initrd映像创建页表项和访问能力 */
    /* create all userland image frames */
    create_frames_ret =
        create_frames_of_region(
            root_cnode_cap,     /*Z CNode */
            it_vspace_cap,      /*Z VSpace */
            ui_reg,             /*Z initrd映像线性区域 */
            true,
            ui_info.pv_offset
        );
    if (!create_frames_ret.success) {
        return false;
    }
    ndks_boot.bi_frame->userImageFrames = create_frames_ret.region;
    /*Z 为initrd创建ASID(PCID) pool能力，并关联其VSpace */
    /* create the initial thread's ASID pool */
    it_ap_cap = create_it_asid_pool(root_cnode_cap);
    if (cap_get_capType(it_ap_cap) == cap_null_cap) {
        return false;
    }
    write_it_asid_pool(it_ap_cap, it_vspace_cap);

#ifdef CONFIG_KERNEL_MCS
    NODE_STATE(ksCurTime) = getCurrentTime();/*Z 获取当前TSC计数值 */
#endif
    /*Z 创建idle线程 */
    /* create the idle thread */
    if (!create_idle_thread()) {
        return false;
    }
    /*Z 填充TCB CNode和tcb_t有关数据结构，创建initrd线程 */
    /* create the initial thread */
    tcb_t *initial = create_initial_thread(root_cnode_cap,  /*Z CNode */
                                           it_vspace_cap,   /*Z VSpace */
                                           ui_info.v_entry, /*Z ELF入口点虚拟地址 */
                                           bi_frame_vptr,   /*Z bootinfo虚拟地址 */
                                           ipcbuf_vptr,     /*Z IPC buffer虚拟地址 */
                                           ipcbuf_cap);     /*Z IPC buffer能力 */
    if (initial == NULL) {
        return false;
    }
    init_core_state(initial);/*Z 初始化系统运行状态，设置调度器预选对象 */
    /*Z 创建IOMMU各种表、寄存器和中断，将每个老旧设备DMA保留内存区映射为一个独立域和页表，使能DMA重映射 */
#ifdef CONFIG_IOMMU
    /* initialise VTD-related data structures and the IOMMUs */
    if (!vtd_init(cpu_id, rmrr_list)) {
        return false;
    }

    /* write number of IOMMU PT levels into bootinfo */
    ndks_boot.bi_frame->numIOPTLevels = x86KSnumIOPTLevels;
    /*Z 创建IO空间域0的控制能力 */
    /* write IOSpace master cap */
    write_slot(SLOT_PTR(pptr_of_cap(root_cnode_cap), seL4_CapIOSpace), master_iospace_cap());
#else
    ndks_boot.bi_frame->numIOPTLevels = -1;/*Z 不好：变量定义的注释上说是0 */
#endif
    /*Z 设备RAM、ROM，空闲内存和内核启动内存，作为untyped，记录在ndks_boot中，并在根CNode中创建相应的能力 */
    /* create all of the untypeds. Both devices and kernel window memory */
    if (!create_untypeds(root_cnode_cap, boot_mem_reuse_reg)) {
        return false;
    }
    /*Z 在即将启动结束前，记录根CNode中剩余的空闲CSlot */
    /* finalise the bootinfo frame */
    bi_finalise();

    return true;
}

/* This function initialises the CPU. It does NOT initialise any kernel state. */
/*Z x86的启动代码部分：初始化TSS段、GDT、IDT表，加载内存管理寄存器GDTR、IDTR、LDTR、TR，
初始化系统调用指令、PAT页缓存属性、分支预测、APIC等MSR寄存器，设置CR0、CR4保护位、定时器、FPU，
可配置地设置VMX虚拟机支持，进入VMM管理模式 */
BOOT_CODE bool_t init_cpu(
    bool_t   mask_legacy_irqs
)
{   /*Z 初始化当前cpu的TSS段(设置中断栈、禁用用户I/O端口操作)、GDT、IDT表 */
    /* initialise virtual-memory-related data structures */
    if (!init_vm_state()) {
        return false;
    }
    /*Z 加载内存管理寄存器GDTR、IDTR、LDTR、TR */
    /* initialise CPU's descriptor table registers (GDTR, IDTR, LDTR, TR) */
    init_dtrs();
    /*Z 初始化系统调用指令相关MSR寄存器 */
    if (config_set(CONFIG_SYSENTER)) {
        /* initialise MSRs (needs an initialised TSS) */
        init_sysenter_msrs();/*Z 设置sysenter/sysexit快速系统调用入口 */
    } else if (config_set(CONFIG_SYSCALL)) {
        init_syscall_msrs();/*Z 初始化syscall/sysret指令有关MSR寄存器 */
    } else {
        return false;
    }
    /*Z 设置PAT页缓存属性 */
    /* setup additional PAT MSR */
    if (!init_pat_msr()) {
        return false;
    }
    /*Z 设置CR0的写保护位，禁止特权代码写只读内存页，这样在写时会触发COW机制 */
    /* enable the Write Protect bit in cr0. This prevents the kernel from writing to
     * read only memory, which we shouldn't do under correct execution */
    write_cr0(read_cr0() | CR0_WRITE_PROTECT);
    /*Z 启用CR4.SMAP位阻止一定条件下特权代码访问普通级别的数据 */
    /* check for SMAP and SMEP and enable */
    cpuid_007h_ebx_t ebx_007;
    ebx_007.words[0] = x86_cpuid_ebx(0x7, 0);
    if (cpuid_007h_ebx_get_smap(ebx_007)) {
        /* if we have user stack trace enabled or dangerous code injection then we cannot
         * enable this as SMAP will make them fault. */
        if (!config_set(CONFIG_PRINTING) && !config_set(CONFIG_DANGEROUS_CODE_INJECTION)) {
            write_cr4(read_cr4() | CR4_SMAP);
        }
    }/*Z 启用CR4.SMEP位阻止特权代码执行用户空间指令 */
    if (cpuid_007h_ebx_get_smep(ebx_007)) {
        /* similar to smap we cannot enable smep if using dangerous code injection. it
         * does not affect stack trace printing though */
        if (!config_set(CONFIG_DANGEROUS_CODE_INJECTION)) {
            write_cr4(read_cr4() | CR4_SMEP);
        }
    }
    /*Z 与分支预测有关的设置 */
    if (!init_ibrs()) {
        return false;
    }
    /*Z 检查CPU是否支持8字节断点区域 */
#ifdef CONFIG_HARDWARE_DEBUG_API
    /* Initialize hardware breakpoints */
    Arch_initHardwareBreakpoints();
#endif
    /*Z 初始化FPU状态、配置 */
    /* initialise floating-point unit */
    if (!Arch_initFpu()) {
        return false;
    }
    /*Z 初始化APIC，配置定时器等 */
    /* initialise local APIC */
    if (!apic_init(mask_legacy_irqs)) {
        return false;
    }

#ifdef CONFIG_DEBUG_DISABLE_PREFETCHERS
    if (!disablePrefetchers()) {/*Z 禁用数据缓存预取 */
        return false;
    }
#endif
    /*Z 允许普通用户读取性能监测计数器 */
    if (config_set(CONFIG_EXPORT_PMC_USER)) {
        enablePMCUser();
    }

#ifdef CONFIG_VTX
    /* initialise Intel VT-x extensions *//*Z 设置VMX虚拟机支持，进入VMM管理模式 */
    if (!vtx_init()) {
        return false;
    }
#endif

    return true;
}
